﻿/*
 * Project: IV:MP GUI Editor (http://code.google.com/p/ivmp-gui-editor)
 * Code license: GNU Lesser GPL (http://www.gnu.org/copyleft/lesser.html)
 * 
 * Authors: CrackHD
 * Description: Lock file is used instead of Mutex as more safe alternative
 */

using System;
using System.IO;
using System.Threading;

namespace IvmpEditor
{
    public class LockFile
    {
        Stream lockStream;
        public readonly string FileName;
        public LockFile(string fileName)
        {
            Common.ToAbsolutePath(ref fileName, Common.DirCommonAppData);
            FileName = fileName;
        }

        public bool TryHold()
        {
            try { lockStream = File.Open(FileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None); }
            catch (IOException) { return false; }

            return true;
        }
        public enum TimedHoldkResult { Failed, Done, Aborted };
        public bool IsHolden { get { return lockStream != null; } }
        public TimedHoldkResult TryHold(int timeout, ref bool abort)
        {
            var i = 200;
            if (timeout < i)
                return TryHold() ? TimedHoldkResult.Done : TimedHoldkResult.Failed;

            var spendTimeout = 0;
            while (spendTimeout < timeout)
            {
                if (abort == true)
                    return TimedHoldkResult.Aborted;
                else if (TryHold())
                    return TimedHoldkResult.Done;
                else
                {
                    Thread.Sleep(i);
                    spendTimeout += i;
                }
            }
            return TimedHoldkResult.Failed;
        }
        public bool TryHold(int msTimeout)
        {
            bool dummy = false;
            return this.TryHold(msTimeout, ref dummy) == TimedHoldkResult.Done;
        }
        public void Release()
        {
            if (!IsHolden)
                return;

            lockStream.Close();
            lockStream.Dispose();
            lockStream = null;
            try { File.Delete(FileName); }
            catch { }
        }
    }
}